﻿using System;
using System.Collections.Generic;
using System.Linq;
using Mvc3App.Dominio;
using NHibernate;
using NHibernate.Criterion;

namespace Mvc3App.Repositorio
{
    public class SocioNHRepository : IRepository<Socio>
    {
        protected ISession GetSession()
        {
            return NHibernateHelper.GetCurrentSession();
        }

        #region Implementation of IRepository<Socio>

        public virtual Socio GetOne(object id)
        {
            return GetSession().Get<Socio>(id);
        }

        public virtual long Count()
        {
            var criteria = GetSession().CreateCriteria<Socio>();
            criteria.SetProjection(Projections.RowCount());
            var countMayBeInt32OrInt64DependingOnDatabase = criteria.UniqueResult();
            
            return Convert.ToInt64(countMayBeInt32OrInt64DependingOnDatabase);
        }

        public virtual void Add(Socio entity)
        {
            GetSession().Save(entity);
        }

        public virtual void Add(IEnumerable<Socio> entities)
        {
            foreach (var entity in entities)
            {
                Add(entity);
            }
        }

        public virtual void Update(Socio entity)
        {
            GetSession().Update(entity);
        }

        public virtual void Delete(object id)
        {
            var entity = GetOne(id);
            GetSession().Delete(entity);
        }

        public virtual void Delete(Socio entity)
        {
            if (GetSession().Contains(entity))
                GetSession().Load(entity, entity.Id);

            GetSession().Delete(entity);
        }

        public virtual IEnumerable<Socio> GetSlice(int slice, int quantity, string order, bool ascending)
        {           
            return GetSession().CreateCriteria<Socio>()
                    .SetFirstResult(slice * quantity)
                    .SetMaxResults(quantity)
                    .AddOrder(new Order(order, ascending))
                    .List<Socio>();
        }

        #endregion

        public virtual IEnumerable<Socio> GetAll(string orderByField, bool ascending)
        {
            return GetSession().CreateCriteria<Socio>()
                .AddOrder(new Order(orderByField, ascending))
                .List<Socio>();
        }

        public virtual IEnumerable<Socio> GetAll()
        {
            return GetSession().CreateCriteria<Socio>().List<Socio>();
        }

        public IEnumerable<Socio> GetByFiltro(string name, string lastname, string dni)
        {
            return GetAll().Where(x => (string.IsNullOrEmpty(name) || x.Nombre.Contains(name)) &&
                (string.IsNullOrEmpty(lastname) || x.Apellido.Contains(lastname)) &&
                (string.IsNullOrEmpty(dni) || x.Documento.Contains(dni)));
        }

        public IEnumerable<Socio> GetSliceByFilter(int slice, int quantity, Func<Socio, IComparable> order, bool ascending, string name, string lastname, string dni)
        {
            var resultFilters = GetByFiltro(name, lastname, dni);
            //var resultFilters = FindByFilters(name, lastname, dni);
            IEnumerable<Socio> result = ascending ? resultFilters.OrderBy(order) : resultFilters.OrderByDescending(order);
            return result.Skip((slice - 1) * quantity).Take(quantity);
        }

        public IEnumerable<Socio> FindByFilters(string name, string lastname, string dni)
        {
            var criteria = GetSession().CreateCriteria<Socio>();

            if (!string.IsNullOrEmpty(name))
            {
                criteria.Add(Restrictions.InsensitiveLike("Nombre", name));    
            }

            if (!string.IsNullOrEmpty(lastname))
            {
                criteria.Add(Restrictions.InsensitiveLike("Apellido", lastname));
            }

            if (!string.IsNullOrEmpty(dni))
            {
                criteria.Add(Restrictions.InsensitiveLike("Documento", dni));
            }

            return criteria.List<Socio>();
        }
    }
}